#网络基础脚本，包含了myNet的相关方法

ROOTDIR=$(cd "$(dirname "$0")" && pwd)
export PATH=${ROOTDIR}/../bin:${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
export VERBOSE=false

pushd ${ROOTDIR} > /dev/null
trap "popd > /dev/null" EXIT

. scripts/utils.sh

: ${CONTAINER_CLI:="docker"}
: ${CONTAINER_CLI_COMPOSE:="${CONTAINER_CLI}-compose"}
infoln "Using ${CONTAINER_CLI} and ${CONTAINER_CLI_COMPOSE}"

function clearContainers() {
  infoln "Removing remaining containers"
  ${CONTAINER_CLI} rm -f $(${CONTAINER_CLI} ps -aq --filter label=service=hyperledger-fabric) 2>/dev/null || true
  ${CONTAINER_CLI} rm -f $(${CONTAINER_CLI} ps -aq --filter name='dev-peer*') 2>/dev/null || true
}

function removeUnwantedImages() {
  infoln "Removing generated chaincode docker images"
  ${CONTAINER_CLI} image rm -f $(${CONTAINER_CLI} images -aq --filter reference='dev-peer*') 2>/dev/null || true
}

NONWORKING_VERSIONS="^1\.0\. ^1\.1\. ^1\.2\. ^1\.3\. ^1\.4\."

#使用fabric-CA为peer节点生成加密材料
function createOrgs() {
  if [ -d "organizations/peerOrganizations" ]; then
    rm -Rf organizations/peerOrganizations && rm -Rf organizations/ordererOrganizations
  fi

  if [ "$CRYPTO" == "Certificate Authorities" ]; then
    infoln "Generating certificates using Fabric CA"

    #docker-compose -f compose/compose-ca.yaml up -d 2>&1
    ${CONTAINER_CLI_COMPOSE} -f compose/$COMPOSE_FILE_CA -f compose/$CONTAINER_CLI/${CONTAINER_CLI}-$COMPOSE_FILE_CA up -d 2>&1

    . organizations/fabric-ca/registerEnroll.sh

    while :
    do
      if [ ! -f "organizations/fabric-ca/org1/tls-cert.pem" ]; then
        sleep 1
      else
        break
      fi
    done

    infoln "Creating Org1 Identities"

    createOrg1

    infoln "Creating Org2 Identities"

    createOrg2

    infoln "Creating Org3 Identities"

    createOrg3

    infoln "Creating Orderer Org Identities"

    createOrderer

  fi

  infoln "Generating CCP files for Org1,Org2 and Org3"
  ./organizations/ccp-config/ccp-org1/ccp-generate.sh
  ./organizations/ccp-config/ccp-org2/ccp-generate.sh
  ./organizations/ccp-config/ccp-org3/ccp-generate.sh
}

# Bring up the peer and orderer nodes using docker compose.
function networkUp() {

  # generate artifacts if they don't exist
  if [ ! -d "organizations/peerOrganizations" ]; then
    createOrgs
  fi

  COMPOSE_FILES="-f compose/${COMPOSE_FILE_BASE} -f compose/${CONTAINER_CLI}/${CONTAINER_CLI}-${COMPOSE_FILE_BASE}"

  if [ "${DATABASE}" == "couchdb" ]; then
    COMPOSE_FILES="${COMPOSE_FILES} -f compose/${COMPOSE_FILE_COUCH} -f compose/${CONTAINER_CLI}/${CONTAINER_CLI}-${COMPOSE_FILE_COUCH}"
  fi

  DOCKER_SOCK="${DOCKER_SOCK}" ${CONTAINER_CLI_COMPOSE} ${COMPOSE_FILES} up -d 2>&1
  
  #docker-compose -f compose/compose-myNet.yaml -f compose/docker/docker-compose-myNet.yaml -f compose/compose-couch.yaml up -d 2>&1

  $CONTAINER_CLI ps -a
  if [ $? -ne 0 ]; then
    fatalln "Unable to start network"
  fi
}

function createChannel() {
  scripts/createChannel1/createChannel.sh $CHANNEL_NAME1 $CLI_DELAY $MAX_RETRY $VERBOSE

  scripts/createChannel2/createChannel.sh $CHANNEL_NAME2 $CLI_DELAY $MAX_RETRY $VERBOSE
}

#为channel1部署链码
function deployCC1() {
  scripts/deployCC/deployCC1/deployCC.sh $CHANNEL_NAME $CC_NAME $CC_SRC_PATH $CC_SRC_LANGUAGE $CC_VERSION $CC_SEQUENCE $CC_INIT_FCN $CC_END_POLICY $CC_COLL_CONFIG $CLI_DELAY $MAX_RETRY $VERBOSE
  #./network.sh deployCCA -c channela -ccn basic -ccp chaincode-js -ccl javascript
  if [ $? -ne 0 ]; then
    fatalln "Deploying chaincode failed"
  fi
}

#为channel2部署链码
function deployCC2() {
  scripts/deployCC/deployCC2/deployCC.sh $CHANNEL_NAME $CC_NAME $CC_SRC_PATH $CC_SRC_LANGUAGE $CC_VERSION $CC_SEQUENCE $CC_INIT_FCN $CC_END_POLICY $CC_COLL_CONFIG $CLI_DELAY $MAX_RETRY $VERBOSE
  #./network.sh deployCC channelB -ccn basic -ccp ../chaincode-js/chaincode2 -ccl javascript
  if [ $? -ne 0 ]; then
    fatalln "Deploying chaincode failed"
  fi
}

#查询通道1的区块
function checkBlock1() {
  ${CONTAINER_CLI} exec cli ./scripts/checkBlocks/checkBlockC1.sh $NUM
  docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/${NUM}Block1.json blockFiles/

  # only show the number of this block
  jq '.header' blockFiles/${NUM}Block1.json | jq 'del(.data_hash)' | jq -c 'del(.previous_hash)' | cat

  # show all info of header
  # jq '.header' ${NUM}Block1.json | cat
}

#查询通道2的区块
function checkBlock2() {
  ${CONTAINER_CLI} exec cli ./scripts/checkBlocks/checkBlockC2.sh $NUM
  docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/${NUM}Block2.json blockFiles/

   # only show the number of this block
  jq '.header' blockFiles/${NUM}Block2.json | jq 'del(.data_hash)' | jq -c 'del(.previous_hash)' | cat

  # show all info of header
  # jq '.header' ${NUM}Block2.json | cat
}

#为3个组织创建wallet
function createWallets(){
  node appBack/appRun/utils/createWallets.js
}

# Tear down running network
function networkDown() {
  docker stop $(docker ps -a -q)
  docker rm $(docker ps -a -q)
  docker system prune --volumes -f
}

# Using crpto vs CA. default is cryptogen
CRYPTO="Certificate Authorities"
# timeout duration - the duration the CLI should wait for a response from
# another container before giving up
MAX_RETRY=5
# default for delay between commands
CLI_DELAY=3
# channel names
CHANNEL_NAME1="channel1"
CHANNEL_NAME2="channel2"
# chaincode name defaults to "NA"
CC_NAME="NA"
# chaincode path defaults to "NA"
CC_SRC_PATH="NA"
# endorsement policy defaults to "NA". This would allow chaincodes to use the majority default policy.
CC_END_POLICY="NA"
# collection configuration defaults to "NA"
CC_COLL_CONFIG="NA"
# chaincode init function defaults to "NA"
CC_INIT_FCN="NA"
# use this as the default docker-compose yaml definition
COMPOSE_FILE_BASE=compose-myNet.yaml
# docker-compose.yaml file if you are using couchdb
COMPOSE_FILE_COUCH=compose-couch.yaml
# certificate authorities compose file
COMPOSE_FILE_CA=compose-ca.yaml
#
# chaincode language defaults to "NA"
CC_SRC_LANGUAGE="NA"
# default to running the docker commands for the CCAAS
CCAAS_DOCKER_RUN=true
# Chaincode version
CC_VERSION="1.0"
# Chaincode definition sequence
CC_SEQUENCE=1
# default database
DATABASE="couchdb"

# Get docker sock path from environment variable
SOCK="${DOCKER_HOST:-/var/run/docker.sock}"
DOCKER_SOCK="${SOCK##unix://}"

# Parse commandline args

## Parse mode
if [[ $# -lt 1 ]] ; then
  printHelp
  exit 0
else
  MODE=$1
  shift
fi

# parse a createChannel subcommand if used
if [[ $# -ge 1 ]] ; then
  key="$1"
  if [[ "$key" == "createChannel" ]]; then
      export MODE="createChannel"
      shift
  fi
fi

# parse flags

while [[ $# -ge 1 ]] ; do
  key="$1"
  case $key in
  -h )
    printHelp $MODE
    exit 0
    ;;
  -c )
    CHANNEL_NAME="$2"
    shift
    ;;
  -ca )
    CRYPTO="Certificate Authorities"
    ;;
  -r )
    MAX_RETRY="$2"
    shift
    ;;
  -d )
    CLI_DELAY="$2"
    shift
    ;;
  -s )
    DATABASE="$2"
    shift
    ;;
  -ccl )
    CC_SRC_LANGUAGE="$2"
    shift
    ;;
  -ccn )
    CC_NAME="$2"
    shift
    ;;
  -ccv )
    CC_VERSION="$2"
    shift
    ;;
  -ccs )
    CC_SEQUENCE="$2"
    shift
    ;;
  -ccp )
    CC_SRC_PATH="$2"
    shift
    ;;
  -ccep )
    CC_END_POLICY="$2"
    shift
    ;;
  -cccg )
    CC_COLL_CONFIG="$2"
    shift
    ;;
  -cci )
    CC_INIT_FCN="$2"
    shift
    ;;
  -ccaasdocker )
    CCAAS_DOCKER_RUN="$2"
    shift
    ;;
  -verbose )
    VERBOSE=true
    ;;
  -num )
    NUM="$2"
    shift
    ;;
  * )
    errorln "Unknown flag: $key"
    printHelp
    exit 1
    ;;
  esac
  shift
done

# Are we generating crypto material with this command?
if [ ! -d "organizations/peerOrganizations" ]; then
  CRYPTO_MODE="with crypto from '${CRYPTO}'"
else
  CRYPTO_MODE=""
fi

# Determine mode of operation and printing out what we asked for
if [ "$MODE" == "up" ]; then
  infoln "Starting nodes with CLI timeout of '${MAX_RETRY}' tries and CLI delay of '${CLI_DELAY}' seconds and using database '${DATABASE}' ${CRYPTO_MODE}"
  networkUp
elif [ "$MODE" == "createChannel" ]; then
  infoln "Creating channel channelA."
  infoln "If network is not up, starting nodes with CLI timeout of '${MAX_RETRY}' tries and CLI delay of '${CLI_DELAY}' seconds and using database '${DATABASE} ${CRYPTO_MODE}"
  createChannel
elif [ "$MODE" == "down" ]; then
  infoln "Stopping network"
  networkDown
elif [ "$MODE" == "deployCC1" ]; then
  infoln "deploying chaincode on channel '${CHANNEL_NAME_A}'"
  deployCC1
elif [ "$MODE" == "deployCC2" ]; then
  infoln "deploying chaincode on channel '${CHANNEL_NAME_B}'"
  deployCC2
elif [ "$MODE" == "checkBlock1" ]; then
  infoln "check channel1 block..."
  checkBlock1
elif [ "$MODE" == "checkBlock2" ]; then
  infoln "check channel1 block..."
  checkBlock2
elif [ "$MODE" == "createWallets" ]; then
  infoln "create wallets for org1,org2,org3"
  createWallets
else
  printHelp
  exit 1
fi
